#include "event.h"

using namespace MidiFile;
using namespace std;

//------------------------------------------------------------------------------
// Constructores y destructor
//------------------------------------------------------------------------------

Event::Event(const Event &other) throw ()
{
    eventType = other.eventType;
    deltaTime = other.deltaTime;
    
    switch (eventType)
    {
    case Meta:
        metaEventType = other.metaEventType;
        
    case SysEx:
    case SysExCont:
        strData = other.strData;
        break;
        
    default:
        midiChannel = other.midiChannel;
        parameter1 = other.parameter1;
        parameter2 = other.parameter2;
    }
}

//------------------------------------------------------------------------------
// Propiedades: getters
//------------------------------------------------------------------------------

char Event::getMidiChannel() const throw (InvalidException)
{
    if ((eventType & 0xF0) == 0xF0)
        throw InvalidException();
    
    return midiChannel;
}

char Event::getNoteNumber() const throw (InvalidException)
{
    switch (eventType)
    {
    case NoteOff:
    case NoteOn:
    case NoteAftertouch:
        return parameter1;
        
    default:
        throw InvalidException();
    }
}

char Event::getVelocity() const throw (InvalidException)
{
    switch (eventType)
    {
    case NoteOff:
    case NoteOn:
        return parameter2;
        
    default:
        throw InvalidException();
    }
}

char Event::getAmount() const throw (InvalidException)
{
    switch (eventType)
    {
    case NoteAftertouch:
        return parameter2;
        
    case ChannelAftertouch:
        return parameter1;
        
    default:
        throw InvalidException();
    }
}

char Event::getControllerType() const throw (InvalidException)
{
    if (eventType != Controller)
        throw InvalidException();
    
    return parameter1;
}

char Event::getControllerValue() const throw (InvalidException)
{
    if (eventType != Controller)
        throw InvalidException();
    
    return parameter2;
}

char Event::getProgramNumber() const throw (InvalidException)
{
    if (eventType != ProgramChange)
        throw InvalidException();
    
    return parameter1;
}

short Event::getPitchBend() const throw (InvalidException)
{
    if (eventType != PitchBend)
        throw InvalidException();
    
    return (parameter1 & 0x7F) | ((parameter2 & 0xF7) << 7);
}

MetaEventType Event::getMetaEventType() const throw (InvalidException)
{
    if (eventType != Meta)
        throw InvalidException();
    
    return metaEventType;
}

string Event::getDataString() const throw (InvalidException)
{
    switch (eventType)
    {
    case Meta:
    case SysEx:
    case SysExCont:
        return strData;
        
    default:
        throw InvalidException();
    }
}

//------------------------------------------------------------------------------
// Propiedades: setters
//------------------------------------------------------------------------------

void Event::setMidiChannel(char value) throw (InvalidException)
{
    if ((eventType & 0xF0) == 0xF0)
        throw InvalidException();
    
    midiChannel = value;
}

void Event::setNoteNumber(char value) throw (InvalidException)
{
    switch (eventType)
    {
    case NoteOff:
    case NoteOn:
    case NoteAftertouch:
        parameter1 = value;
        break;
        
    default:
        throw InvalidException();
    }
}

void Event::setVelocity(char value) throw (InvalidException)
{
    switch (eventType)
    {
    case NoteOff:
    case NoteOn:
        parameter2 = value;
        break;
        
    default:
        throw InvalidException();
    }
}

void Event::setAmount(char value) throw (InvalidException)
{
    switch (eventType)
    {
    case NoteAftertouch:
        parameter2 = value;
        break;
        
    case ChannelAftertouch:
        parameter1 = value;
        break;
        
    default:
        throw InvalidException();
    }
}

void Event::setControllerType(char value) throw (InvalidException)
{
    if (eventType != Controller)
        throw InvalidException();
    
    parameter1 = value;
}

void Event::setControllerValue(char value) throw (InvalidException)
{
    if (eventType != Controller)
        throw InvalidException();
    
    parameter2 = value;
}

void Event::setProgramNumber(char value) throw (InvalidException)
{
    if (eventType != ProgramChange)
        throw InvalidException();
    
    parameter1 = value;
}

void Event::setPitchBend(short value) throw (InvalidException)
{
    if (eventType != PitchBend)
        throw InvalidException();
    
    parameter1 = value & 0x7F;
    parameter2 = value >> 7;
}

void Event::setPitchBend(char param1, char param2) throw (InvalidException)
{
    if (eventType != PitchBend)
        throw InvalidException();
    
    parameter1 = param1;
    parameter2 = param2;
}

void Event::setMetaEventType(MetaEventType value) throw (InvalidException)
{
    if (eventType != Meta)
        throw InvalidException();
    
    metaEventType = value;
}
void Event::setData(const char *data, int length) throw (InvalidException)
{
    switch (eventType)
    {
    case Meta:
    case SysEx:
    case SysExCont:
        strData = string(data, length);
        break;
        
    default:
        throw InvalidException();
    }
}

void Event::setDataString(const string &value) throw (InvalidException)
{
    switch (eventType)
    {
    case Meta:
    case SysEx:
    case SysExCont:
        strData = value;
        break;
        
    default:
        throw InvalidException();
    }
}
